package com.biz.primus.ms.depot.dao.redis;


import com.biz.primus.base.enums.DepotType;
import com.biz.primus.base.redis.CrudRedisDao;
import com.biz.primus.base.redis.util.RedisUtil;
import com.biz.primus.ms.depot.dao.ro.DepotRo;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Repository;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author JKLiues
 * @date 2017/10/21
 */
@Repository
public class DepotRedisDao extends CrudRedisDao<DepotRo, Long> {

    /**
     * 重载save方法
     * 映射depotCode->depotId 根据门店编码查门店
     * 映射geoId->depotId 根据门店编码查门店
     * 映射centerDepotList 所有总仓
     */
    @Override
    public void save(DepotRo ro) {
        super.save(ro);
        this.addMapping(ro);
    }
    @Override
    public void save(Iterable<DepotRo> ros) {
        super.save(ros);
        ros.forEach(this::addMapping);
    }


    /**
     * 获取所有总仓的信息
     */
    public List<DepotRo> findAllCenterDepots() {
        Set<byte[]> byteIds = smembers(this.centerDepotListMappingKey());
        if (CollectionUtils.isNotEmpty(byteIds)) {
            return super.findByIds(byteIds);
        }
        return Lists.newArrayList();
    }

    /**
     * 获取所有本仓的信息
     */
    public List<DepotRo> findAllHomeDepots() {
        Set<byte[]> byteIds = smembers(this.homeDepotListMappingKey());
        if (CollectionUtils.isNotEmpty(byteIds)) {
            return super.findByIds(byteIds);
        }
        return Lists.newArrayList();
    }

    /**
     * 根据门店编号查询depot ro
     *
     * @param depotCode 门店编码
     */
    public DepotRo getByDepotCode(String depotCode) {
        byte[] bs = super.get(depotCode2IdMappingKey(depotCode));
        Long id = RedisUtil.byteArrayToLong(bs);
        return super.findOne(id);
    }

    /**
     * 根据geoId查询到该GEO下所有的门店集合
     *
     * @param geoId 区域ID
     */
    public List<DepotRo> findDepotsByGeoId(Long geoId) {
        Set<byte[]> byteIds = smembers(this.geoIdMappingKey(geoId));
        if (CollectionUtils.isNotEmpty(byteIds)) {
            List<DepotRo> depotRos = findByIds(byteIds);
            return Optional.ofNullable(depotRos).orElse(new ArrayList<>()).stream()
                    .filter(Objects::nonNull).collect(Collectors.toList());
        }
        return Lists.newArrayList();
    }

    /**
     * 根据门店编码的集合查询出门店的集合
     *
     * @param depotCodes 门店编码
     * @return 门店列表
     */
    public List<DepotRo> findDepotsByDepotCodes(List<String> depotCodes) {
        Set<byte[]> depotIds = Sets.newHashSet();
        if (CollectionUtils.isEmpty(depotCodes)) {
            return Lists.newArrayList();
        }
        for (String depotCode : depotCodes) {
            byte[] bytes = super.get(this.depotCode2IdMappingKey(depotCode));
            depotIds.add(bytes);
        }
        depotIds = Optional.of(depotIds).orElse(new HashSet<>()).stream()
                .filter(Objects::nonNull).collect(Collectors.toSet());
        if (CollectionUtils.isEmpty(depotIds)) {
            return new ArrayList<>();
        }
        List<DepotRo> depotRos = this.findByIds(depotIds);
        return depotRos.stream().filter(Objects::nonNull).collect(Collectors.toList());
    }


    private String depotCode2IdMappingKey(String depotCode) {
        return getKeyByParams("depotCode", depotCode);
    }

    private String geoIdMappingKey(Long geoId) {
        return getKeyByParams("geoId", geoId);
    }

    private String centerDepotListMappingKey() {
        return getKeyByParams("centerDepotList");
    }

    private String homeDepotListMappingKey() {
        return getKeyByParams("homeDepotList");
    }

    private void addMapping(DepotRo ro) {
        super.set(depotCode2IdMappingKey(ro.getDepotCode()), RedisUtil.toByteArray(ro.getId()));
        if (ro.getDepotType() == DepotType.HOME) {
            super.sadd(homeDepotListMappingKey(), RedisUtil.toByteArray(ro.getId()));
        } else if (ro.getDepotType() == DepotType.CENTER) {
            super.sadd(centerDepotListMappingKey(), RedisUtil.toByteArray(ro.getId()));
        }
        super.sadd(geoIdMappingKey(ro.getDistrictId()), RedisUtil.toByteArray(ro.getId()));
    }
}
